/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 * */

// AmzServer - Tototoy's server model.
// Author: tonyjobmails@gmail.com (tonyhack).
//
// Define class PacketDefine.
//
// PacketDefine Gives some defines of packet.
//

#ifndef __PACKET__DEFINE__H
#define __PACKET__DEFINE__H

#include "common.h"
#include "buffer_define.h"

namespace amz {

namespace packet {

////////////////////////////////////////////////
// Credible UDP packet protocol.
// 
// Credible UDP protocol format:
// +--------------------------------------------------------------+-----------------------------------------------------------+
// |                              head(32 bits)                              |                          part of user's data                       |
// +----------------+----------+----------+---------------------+-----------------------------------------------------------+
// |         31         |     30     |  29~16  |          15~0          |    max length = 65507[UDP max data length] - 32  |
// +----------------+----------+----------+---------------------+-----------------------------------------------------------+
// | odd/even flag | ack flag | reserve | udp serial number |                               user's data                            |
// +---------------------------------------------------------------+-----------------------------------------------------------+
static uint32 kMTU_UDP = 65507;

static uint32 kMaxCredibleSerialNumber = 65535;
static uint32 kCredibleUDPHeadSize = sizeof(uint32);
static uint32 kMaxCredibleUDPDataSize = kMTU_UDP - kCredibleUDPHeadSize;

static uint32 kCredibleUDPOddEvenFlag = 0x80000000;
static uint32 kCredibleUDPAckFlag = 0x40000000;
static uint32 kCredibleUDPSerialNumberMask = 0x0000FFFF;

#define GET_CREDIBLE_UDP_ODD_EVEN(UDPHead) \
  ((UDPHead & packet::kCredibleUDPOddEvenFlag) >> 31)
#define SET_CREDIBLE_UDP_ODD(UDPHead) \
  (UDPHead | packet::kCredibleUDPOddEvenFlag)
#define SET_CREDIBLE_UDP_EVEN(UDPHead) \
  (UDPHead & ~packet::kCredibleUDPOddEvenFlag)

#define CHECK_CREDIBLE_UDP_ACK(UDPHead) \
  ((UDPHead & packet::kCredibleUDPAckFlag) != 0)
#define SET_CREDIBLE_UDP_ACK(UDPHead) \
  (UDPHead | packet::kCredibleUDPAckFlag)
#define SET_CREDIBLE_UDP_NOT_ACK(UDPHead) \
  (UDPHead & ~packet::kCredibleUDPAckFlag)

#define GET_CREDIBLE_UDP_SERIAL_NUMBER(UDPHead) \
  (UDPHead & packet::kCredibleUDPSerialNumberMask)
////////////////////////////////////////////////


////////////////////////////////////////////////
// Logic packet
static uint32 kPacketHeadSize = sizeof(uint32);

// This use for stream pattern.
static uint32 kMaxPacketSize = 65536;
static uint32 kMaxUserPacketSize = kMaxPacketSize - kPacketHeadSize;

static uint32 kPacketLengthMask = 0x00FFFFFF;
static uint32 kPacketZipFlag = 0xF0000000;
static uint32 kPacketEncFlag = 0x0F000000;

static uint32 kDefaultPacketNumber = 64;

#define GET_PACKET_ZIP_TYPE(flag) \
  ((flag & packet::kPacketZipFlag) >> 28)
#define SET_PACKET_ZIP_TYPE(type) \
  ((type << 28) | packet::kPacketZipFlag)

#define GET_PACKET_ENC_TYPE(flag) \
  ((flag & packet::kPacketEncFlag) >> 24)
#define SET_PACKET_ENC_TYPE(type) \
  ((type << 24) | packet::kPacketEncFlag)
////////////////////////////////////////////////


enum PacketErrorType {
  PACKET_ERROR_SPACE_NOT_ENOUGH = 0,    // space is not enough.
  PACKET_ERROR_PART_PACKET = -1,             // packet is a segmental data.
  PACKET_ERROR_COMPRESS_TYPE = -2,         // unrecognized compressing type.
  PACKET_ERROR_ENCRYPT_TYPE = -3,            // unrecognized encrypting type.
  PACKET_ERROR_IMPORT_SIZE = -4,              // import a invalid size(0).
  PACKET_ERROR_UNKNOWN,
};

}  // namespace packet

}  // namespace amz

#endif  // __PACKET__DEFINE__H
